package com.je.gateway.schedule;

import com.je.gateway.router.GlobalRouterParams;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.ConvertingCursor;
import org.springframework.data.redis.core.Cursor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ScanOptions;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

@Component
public class RouterSyncSchedule {

    /**
     * 已同步KEY
     */
    private static final List<String> SYNCED_CACHE_KEYS = new ArrayList<>();

    @Autowired
    private RedisTemplate<String,Object> redisTemplate;

    @Scheduled(cron = "0/30 * * * * ?")
    public void sync(){
        Set<String> keys = getKeys(GlobalRouterParams.GLOBAL_ROUTER_SYNC_KEY + "*");
        if(keys == null || keys.isEmpty()){
            SYNCED_CACHE_KEYS.clear();
            return;
        }

        boolean flag = false;
        for (String key : keys) {
            if(!SYNCED_CACHE_KEYS.contains(key)){
                SYNCED_CACHE_KEYS.add(key);
                flag = true;
                break;
            }
        }

        if(flag){
            GlobalRouterParams.reload();
        }

    }

    public Set<String> getKeys (String pattern){
        RedisSerializer<String> redisSerializer = (RedisSerializer<String>) redisTemplate.getKeySerializer();
        ScanOptions options = ScanOptions.scanOptions()
                .count(10000)
                .match(pattern)
                .build();

        Cursor<String> cursor = (Cursor<String>) redisTemplate.executeWithStickyConnection(redisConnection ->
                new ConvertingCursor<>(redisConnection.scan(options), redisSerializer::deserialize));
        Set<String> set = new HashSet();
        assert cursor != null;
        while (cursor.hasNext()) {
            set.add(cursor.next());
        }
        cursor.close();
        return set;
    }

}
